/**
 * 音频灯光映射服务
 * 将音频频谱数据映射到键盘灯光效果
 */

import { MatrixResult } from "./matrixProcessor";
import { LightInfo } from "../types/types";

export interface AudioLightMapping {
  // 音频强度到灯光亮度的映射
  intensityToBrightness: (intensity: number) => number;
  // 音频频率到键盘区域的映射
  frequencyToKeyboardRegion: (freqIndex: number) => string;
  // 音频数据到灯光信息的转换
  matrixToLightInfo: (
    matrix: MatrixResult,
    baseLightInfo: LightInfo
  ) => LightInfo[];
  // 实时音频响应
  createReactiveLightInfo: (
    matrix: MatrixResult,
    baseLightInfo: LightInfo
  ) => LightInfo[];
}

export class AudioLightMapper implements AudioLightMapping {
  private keyboardLayout: { rows: number; cols: number };
  private audioMapping: {
    lowFreq: { audioCols: number[]; keyboardRegion: string };
    midFreq: { audioCols: number[]; keyboardRegion: string };
    highFreq: { audioCols: number[]; keyboardRegion: string };
  };

  constructor(
    keyboardLayout: { rows: number; cols: number } = { rows: 6, cols: 22 }
  ) {
    this.keyboardLayout = keyboardLayout;

    // 定义音频频率到键盘区域的映射
    this.audioMapping = {
      // 低频区域 (0-7列) -> 键盘左侧
      lowFreq: {
        audioCols: [0, 1, 2, 3, 4, 5, 6, 7],
        keyboardRegion: "left",
      },
      // 中频区域 (8-13列) -> 键盘中央
      midFreq: {
        audioCols: [8, 9, 10, 11, 12, 13],
        keyboardRegion: "center",
      },
      // 高频区域 (14-21列) -> 键盘右侧
      highFreq: {
        audioCols: [14, 15, 16, 17, 18, 19, 20, 21],
        keyboardRegion: "right",
      },
    };
  }

  /**
   * 将音频强度(0-1)映射到灯光亮度(0-255)
   */
  intensityToBrightness(intensity: number): number {
    // 应用非线性映射，增强视觉效果
    const enhanced = Math.pow(intensity, 0.7); // gamma校正
    return Math.round(enhanced * 255);
  }

  /**
   * 将音频频率索引映射到键盘区域
   */
  frequencyToKeyboardRegion(freqIndex: number): string {
    if (this.audioMapping.lowFreq.audioCols.includes(freqIndex)) {
      return "lowFreq";
    } else if (this.audioMapping.midFreq.audioCols.includes(freqIndex)) {
      return "midFreq";
    } else {
      return "highFreq";
    }
  }

  /**
   * 将音频矩阵转换为灯光信息数组
   */
  matrixToLightInfo(
    matrix: MatrixResult,
    baseLightInfo: LightInfo
  ): LightInfo[] {
    const lightInfos: LightInfo[] = [];

    // 为每个频率区域创建灯光信息
    Object.entries(this.audioMapping).forEach(([region, mapping]) => {
      // 计算该区域的平均强度
      const regionIntensities = mapping.audioCols.map(
        (colIndex) => matrix.colLevels[colIndex] / matrix.rows
      );
      const avgIntensity =
        regionIntensities.reduce((sum, intensity) => sum + intensity, 0) /
        regionIntensities.length;

      // 创建该区域的灯光信息
      const regionLightInfo: LightInfo = {
        ...baseLightInfo,
        name: `Audio_${region}`,
        mode: this.getAudioModeForRegion(region),
        brightness: this.intensityToBrightness(avgIntensity),
        speed: this.intensityToSpeed(avgIntensity),
        colorValue: this.intensityToColor(avgIntensity, region),
        status: avgIntensity > 0.1 ? 1 : 0, // 强度太低时关闭
      };

      lightInfos.push(regionLightInfo);
    });

    return lightInfos;
  }

  /**
   * 创建实时响应的灯光信息
   */
  createReactiveLightInfo(
    matrix: MatrixResult,
    baseLightInfo: LightInfo
  ): LightInfo[] {
    const lightInfos: LightInfo[] = [];

    // 为每个频率列创建独立的灯光信息
    for (let colIndex = 0; colIndex < matrix.cols; colIndex++) {
      const intensity = matrix.colLevels[colIndex] / matrix.rows;
      const region = this.frequencyToKeyboardRegion(colIndex);

      const reactiveLightInfo: LightInfo = {
        ...baseLightInfo,
        name: `Audio_Col_${colIndex}`,
        mode: this.getAudioModeForRegion(region),
        brightness: this.intensityToBrightness(intensity),
        speed: this.intensityToSpeed(intensity),
        colorValue: this.intensityToColor(intensity, region),
        status: intensity > 0.05 ? 1 : 0,
      };

      lightInfos.push(reactiveLightInfo);
    }

    return lightInfos;
  }

  /**
   * 根据区域获取合适的音频模式
   */
  private getAudioModeForRegion(region: string): number {
    const modeMap: { [key: string]: number } = {
      lowFreq: 0x0e, // 低频：汇聚效果
      midFreq: 0x0f, // 中频：扩散效果
      highFreq: 0x10, // 高频：波浪效果
    };
    return modeMap[region] || 0x0e;
  }

  /**
   * 根据强度计算速度
   */
  private intensityToSpeed(intensity: number): number {
    // 强度越高，速度越快（但保持在合理范围内）
    const baseSpeed = 3; // 基础速度
    const speedVariation = Math.round(intensity * 2); // 0-2的变化
    return Math.max(1, Math.min(5, baseSpeed + speedVariation));
  }

  /**
   * 根据强度和区域计算颜色
   */
  private intensityToColor(intensity: number, region: string): number {
    // 基础颜色映射
    const baseColors: { [key: string]: number } = {
      lowFreq: 0xff0000, // 低频：红色
      midFreq: 0x00ff00, // 中频：绿色
      highFreq: 0x0000ff, // 高频：蓝色
    };

    const baseColor = baseColors[region] || 0xffffff;

    // 根据强度调整颜色亮度
    const r = Math.round(((baseColor >> 16) & 0xff) * intensity);
    const g = Math.round(((baseColor >> 8) & 0xff) * intensity);
    const b = Math.round((baseColor & 0xff) * intensity);

    return (r << 16) | (g << 8) | b;
  }

  /**
   * 创建音乐律动模式的灯光信息
   */
  createMusicReactiveMode(
    matrix: MatrixResult,
    baseLightInfo: LightInfo
  ): LightInfo {
    // 计算整体音频强度
    const overallIntensity = matrix.stats.avg;
    const maxIntensity = matrix.stats.max;

    // 创建音乐律动模式的灯光信息
    const musicLightInfo: LightInfo = {
      ...baseLightInfo,
      name: "Music_Reactive",
      mode: 0x0e, // 音乐律动模式
      brightness: this.intensityToBrightness(overallIntensity),
      speed: this.intensityToSpeed(maxIntensity),
      colorValue: this.createDynamicColor(overallIntensity, maxIntensity),
      status: overallIntensity > 0.05 ? 1 : 0,
      colorful: 1, // 启用彩色模式
    };

    return musicLightInfo;
  }

  /**
   * 创建动态颜色（根据音频强度变化）
   */
  private createDynamicColor(intensity: number, maxIntensity: number): number {
    // 使用HSL颜色空间创建动态颜色
    const hue = (Date.now() / 50) % 360; // 随时间变化的色相
    const saturation = Math.min(100, 50 + intensity * 50); // 强度影响饱和度
    const lightness = Math.max(20, 50 - intensity * 30); // 强度影响亮度

    // 转换HSL到RGB
    return this.hslToRgb(hue, saturation, lightness);
  }

  /**
   * HSL转RGB颜色转换
   */
  private hslToRgb(h: number, s: number, l: number): number {
    h = h / 360;
    s = s / 100;
    l = l / 100;

    const c = (1 - Math.abs(2 * l - 1)) * s;
    const x = c * (1 - Math.abs(((h * 6) % 2) - 1));
    const m = l - c / 2;

    let r = 0,
      g = 0,
      b = 0;

    if (h < 1 / 6) {
      r = c;
      g = x;
      b = 0;
    } else if (h < 2 / 6) {
      r = x;
      g = c;
      b = 0;
    } else if (h < 3 / 6) {
      r = 0;
      g = c;
      b = x;
    } else if (h < 4 / 6) {
      r = 0;
      g = x;
      b = c;
    } else if (h < 5 / 6) {
      r = x;
      g = 0;
      b = c;
    } else {
      r = c;
      g = 0;
      b = x;
    }

    const red = Math.round((r + m) * 255);
    const green = Math.round((g + m) * 255);
    const blue = Math.round((b + m) * 255);

    return (red << 16) | (green << 8) | blue;
  }
}

export default AudioLightMapper;
